import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { DatatableModule } from './datatable.module';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';

@Component({
  template: `
    <lv-treetable
      lvSelectionMode="multiple"
      lvCompareWith="data.name"
      [lvSelectionAssociate]="selectionAssociate"
      [lvData]="lvData"
      [lvStripe]="stripe"
      #lvTable
    >
      <thead>
        <tr>
          <th lvCellKey="name">Name</th>
          <th lvCellKey="age">Age</th>
        </tr>
      </thead>
      <tbody>
        <ng-container *ngTemplateOutlet="bodyContentTpl; context: { $implicit: lvTable.renderData }"></ng-container>
        <ng-template #bodyContentTpl let-data>
          <ng-container *ngFor="let item of data">
            <tr>
              <td [lvRowData]="item" lvShowCheckbox [lvShowExpanded]="item.children?.length" [(lvExpanded)]="item.expanded">
                {{ item.data.name }}
              </td>
              <td>{{ item.data.age }}</td>
            </tr>
            <ng-container *ngIf="item.expanded && item.children?.length">
              <ng-container *ngTemplateOutlet="bodyContentTpl; context: { $implicit: item.children }"></ng-container>
            </ng-container>
          </ng-container>
        </ng-template>
      </tbody>
    </lv-treetable>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
class TestTreeTableComponent {
  lvData = [
    {
      data: {
        name: 'user0',
        age: 10,
      },
      expanded: true,
      children: [
        {
          data: {
            name: 'user00',
            age: 10,
          },
        },
        {
          data: {
            name: 'user01',
            age: 11,
          },
        },
        {
          data: {
            name: 'user02',
            age: 12,
          },
          disabled: true,
        },
      ],
    },
    {
      data: {
        name: 'user1',
        age: 11,
      },
      children: [
        {
          data: {
            name: 'user10',
            age: 20,
          },
        },
        {
          data: {
            name: 'user11',
            age: 21,
          },
        },
      ],
    },
  ];
  stripe = false;
  selectionAssociate = true;
}
describe('TreeTableComponent', () => {
  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        declarations: [TestTreeTableComponent],
        imports: [DatatableModule, NoopAnimationsModule],
        teardown: { destroyAfterEach: true },
      }).compileComponents();
    })
  );

  describe('render', () => {
    let component: TestTreeTableComponent;
    let fixture: ComponentFixture<TestTreeTableComponent>;

    beforeEach(fakeAsync(() => {
      fixture = TestBed.createComponent(TestTreeTableComponent);
      component = fixture.componentInstance;
      fixture.detectChanges();
      tick(500);
    }));

    // lvStripe斑马纹渲染
    it('with lvStripe', fakeAsync(() => {
      component.stripe = true;
      tick(500);
      fixture.detectChanges();
      expect(fixture).toMatchSnapshot();
    }));
  });

  describe('work', () => {
    let component: TestTreeTableComponent;
    let fixture: ComponentFixture<TestTreeTableComponent>;

    const updateView = () => {
      tick(500);
      fixture.detectChanges();
      tick(500);
      fixture.detectChanges();
    };

    const getChecked = () => fixture.nativeElement.querySelectorAll('.lv-checkbase-checked');

    beforeEach(fakeAsync(() => {
      fixture = TestBed.createComponent(TestTreeTableComponent);
      component = fixture.componentInstance;
    }));

    // lvSelectionAssociate传入为false时，父子节点非关联选中；切换选中项
    test('correctly with lvSelectionAssociate', fakeAsync(() => {
      component.selectionAssociate = false;
      updateView();

      const checkbox = fixture.nativeElement.querySelectorAll('.lv-checkbase');
      checkbox[0].dispatchEvent(new Event('click'));
      updateView();
      expect(getChecked().length).toBe(1);
    }));

    // 祖先联动：子全部选中，父判断是否子都全选（反选）改变选中状态
    test('correctly when children checked', fakeAsync(() => {
      updateView();
      const checkbox = fixture.nativeElement.querySelectorAll('.lv-checkbase');
      checkbox[1].dispatchEvent(new Event('click'));
      checkbox[2].dispatchEvent(new Event('click'));
      updateView();
      expect(getChecked().length).toBe(3);

      checkbox[1].dispatchEvent(new Event('click'));
      updateView();
      expect(getChecked().length).toBe(1);
    }));

    // 后代联动：父选中（反选），子（除去disabled状态子）全选中
    test('correctly when parent checked', fakeAsync(() => {
      updateView();
      const checkbox = fixture.nativeElement.querySelectorAll('.lv-checkbase');
      checkbox[0].dispatchEvent(new Event('click'));
      updateView();
      expect(getChecked().length).toBe(3);

      checkbox[0].dispatchEvent(new Event('click'));
      updateView();
      expect(getChecked().length).toBe(0);
    }));
  });
});
